package com.bestom.sharingbookcase.services;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;

import com.bestom.sharingbookcase.entity.GetBean;
import com.bestom.sharingbookcase.entity.InputBean;
import com.bestom.sharingbookcase.entity.PutSuccessBean;
import com.bestom.sharingbookcase.entity.SendHexStep;
import com.bestom.sharingbookcase.entity.TopicStep;
import com.bestom.sharingbookcase.util.DataTurn;
import com.bestom.sharingbookcase.util.FastJsonUtil;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android_serialport_api.SerialPort;

public class SerialManager {

    private static final String TAG = "SerialManager";
    public static SerialManager _instance = null;

    private SerialManager() { }

    public static SerialManager getInstance() {
        if (_instance == null)
            _instance = new SerialManager();
        return _instance;
    }

    private DataTurn mDataTurn;
    private InputStream mInputStream;
    private OutputStream mOutputStream;
    private SerialPort mSerialPort;

    public void openSerialPort(String pathName, int port) {
        try {
            mSerialPort = new SerialPort(new File(pathName), port, 0);
            // 获取输入输出流
            mInputStream = mSerialPort.getInputStream();
            mOutputStream = mSerialPort.getOutputStream();

            readReturnResult();

            Log.d(TAG,"串口打开成功");
        } catch (IOException e) {
            Log.d(TAG,"找不到该设备文件");
        }
    }

    public void writeHexToBoard(String inHex) {
        if (inHex.isEmpty()) {
            Log.d(TAG,"内容为空，请检查");
            return;
        }
        if (mOutputStream == null){
            Log.d(TAG,"send:(" + inHex + ")  发送失败，未打开串口");
            return;
        }
        if (isSpecialChar(inHex)){
            Log.d(TAG,"send:(" + inHex + ")  发送失败，存在非十六进制字符");
            return;
        }
        byte[] bytes = mDataTurn.HexToByteArr(inHex);

        // 写入数据
        try {
            mOutputStream.write(bytes);
            mOutputStream.flush();
            Log.d(TAG,"send:(" + inHex + ")  发送成功");
        } catch (IOException e) {
            Log.d(TAG,"send:(" + inHex + ")  发送失败,流写入异常");
            e.printStackTrace();
        }
    }

    public boolean isSpecialChar(String str) {
        String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？g-zG-Z]|\n|\r|\t";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.find();
    }

    private ReadThread readThread;
    private void readReturnResult(){
        // 开启子线程，不断读取返回结果
        if (mDataTurn == null) mDataTurn = new DataTurn();
        if (readThread == null) readThread = new ReadThread();
        readThread.start();
    }
    private boolean flag = true;
    private final Queue<String> mQueue = new LinkedList<>();
    public synchronized void sendToSerial(String topic, GetBean json) {

        if (json == null) return;
        Log.i(TAG, "json.getDeviceId():" + json.getDeviceId());
        Log.i(TAG, "json.getFunction():" + json.getFunction());
        Log.i(TAG, "json.getProperties():" + Arrays.toString(json.getProperties()));
        Log.i(TAG, "json.getInputs():" + Arrays.toString(json.getInputs()));
        Log.i(TAG, "json.getMessageId():" + json.getMessageId());
        Log.i(TAG, "json.getTimestamp():" + json.getTimestamp());

        String function = json.getFunction();
        String id = "";
        String hex = "";
        String xx = "";

        if (function != null){
            InputBean inputJson = FastJsonUtil.jsonToObjectForFastJson(json.getInputs()[0], InputBean.class);
            switch (function){
                case "openLock":
                    id = inputJson.getValue();
                    hex = SendHexStep.BorrowBooks.getHexString();
                    xx = "05";
                    break;
                case "lockStatus":
                    id = inputJson.getValue();
                    hex = SendHexStep.SelectStatus.getHexString();
                    break;
                case "allLockStatus":
                    break;
                case "saveBook":
                    id = inputJson.getValue();
                    hex = SendHexStep.ReturnBook.getHexString();
                    xx = "05";
                    break;
                case "takeBook":
                    id = inputJson.getValue();
                    hex = SendHexStep.BorrowBooks.getHexString();
                    xx = "06";
                    break;
                case "latticeStatus":
                    break;
                case "syncLattice":
                    break;
                case "playVoice":
                    break;
                default:break;
            }

            mQueue.offer(topic + "-" + json.getMessageId() + "-" + id);
            if (id.length() == 1){
                id = "0" + id;
            }
            writeHexToBoard(getWriteHex(id, hex, xx));
        }else {
            // 文档3.3、属性功能
            String[] properties = json.getProperties();
            if (properties == null) return;
            switch (properties[0]){
                case "powerVoltage":
                    break;
                case "versionInfo":
                    break;
                case "geoPoint":
                    break;
                case "rssi":
                    break;
                default: break;
            }
        }
    }

    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();

            while (flag) {
                try {
                    if (mInputStream.available() <= 0) {
                        continue;
                    } else {
                        Thread.sleep(200);
                    }
                    byte[] buffer = new byte[40];
                    int size = mInputStream.read(buffer);
                    byte[] readBytes = new byte[size];
                    System.arraycopy(buffer, 0, readBytes, 0, size);
                    Log.d(TAG,"Hex data is--->:" + Arrays.toString(mDataTurn.HexToByteArr("5A03C00101C3CC")) + "   readBytes.length:" + readBytes.length);
                    Log.d(TAG,"Hex data is--->:" + mDataTurn.bytesToHex(readBytes) + "   readBytes.length:" + readBytes.length + "   readBytesArrays:" + Arrays.toString(readBytes));
                    if (readBytes.length == 7 || readBytes.length == 14){
                        sendToMQTT(readBytes);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    try { Thread.sleep(2000); } catch (InterruptedException ex) { }
                }
            }

        }


    }
    private synchronized void sendToMQTT(byte[] bytes) {

        String hex = mDataTurn.bytesToHex(bytes);
        String topic = "";
        String messageId = "";
        String msg = "";
        String bookId = "";
        boolean flag = false;
        switch (hex.substring(4,6)){
            case "D0":
                break;
            case "D1":
                break;
            case "C0":
                break;
            case "C1":
            case "c1":
                topic = TopicStep.PublishTopic.getTopicString();
                switch (hex.substring(22, 24)){
                    case "01":
                        flag = true;
                        Log.d(TAG,"开锁成功");
                        String[] strings = mQueue.poll().split("-");
                        messageId = strings[1];
                        bookId = strings[2];
                        Log.d(TAG,"poll-->" + Arrays.toString(strings));
                        break;
                    case "02":
                        Log.d(TAG,"开锁异常之过流");
                        String[] strings2 = mQueue.poll().split("-");
                        messageId = strings2[1];
                        bookId = strings2[2];
                        Log.d(TAG,"poll-->" + Arrays.toString(strings2));
                        break;
                    case "03":
                        Log.d(TAG,"开锁异常之欠流");
                        String[] strings3 = mQueue.poll().split("-");
                        messageId = strings3[1];
                        bookId = strings3[2];
                        Log.d(TAG,"poll-->" + Arrays.toString(strings3));
                        break;
                    case "04":
                        Log.d(TAG,"开锁超时");
                        String[] strings4 = mQueue.poll().split("-");
                        messageId = strings4[1];
                        bookId = strings4[2];
                        Log.d(TAG,"poll-->" + Arrays.toString(strings4));
                        break;
                    default:break;
                }

                PutSuccessBean bean = new PutSuccessBean();
                bean.setDeviceId("BS00001");
                bean.setMessageId(messageId);
                bean.setTimestamp(System.currentTimeMillis());
                bean.setSuccess(flag);
                bean.setProperties(new String[]{"\"functionId\":\"takeBook\",\n" +
                        "\"latticeId\":" + bookId});
                msg = FastJsonUtil.objectToJsonForFastJson(bean);

                break;
            case "C2":
                switch (hex.substring(8, 10)){
                    case "01":
                        Log.d(TAG,"闭锁成功");
                        Log.d(TAG,"poll-->" + mQueue.poll());
                        break;
                    case "02":
                        Log.d(TAG,"闭锁超时");
                        Log.d(TAG,"poll-->" + mQueue.poll());
                        break;
                    default:break;
                }
                break;
            case "F0":
                Log.d(TAG,"子机id --->" + hex.substring(2, 4));
                break;
            case "F1":
                Log.d(TAG,"子机参数 --->" + hex);
                break;
            case "F2":
                switch (hex.substring(8, 10)){
                    case "00":
                        Log.d(TAG,"打开状态");
                        Log.d(TAG,"poll-->" + mQueue.poll());
                        break;
                    case "FF":
                        Log.d(TAG,"闭合状态");
                        Log.d(TAG,"poll-->" + mQueue.poll());
                        break;
                    default:break;
                }
                break;
            case "F3":
                Log.d(TAG,"子机版本 --->" + hex.substring(8, 10));
                break;
            default:break;
        }

        topic = String.format(topic,"BS00001");
        MQTTService.publish(topic,msg);

    }
    /**
     * @param id 书格id ， 01~FF;(其中00禁用,FF针对全局)
     * @param operation 功能指令
     * @param xx 除功能指令外，待定的指令（如书格存书信息更新，借、还书使用）
     *           有则传值，无则传 ""
     * @return 返回经过处理好后组合的十六进制字符串
     */
    public String getWriteHex(String id, String operation, String xx){
        String toXorString = id + operation + xx;
        return String.format(SendHexStep.CommandCombination.getHexString(), toXorString + mDataTurn.xorStringsHex(toXorString));
    }

    public void close(){
        flag = false;
        if (readThread != null){
            readThread.interrupt();
            readThread = null;
        }

        if (mInputStream != null) {
            try {
                mInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mOutputStream != null){
            try {
                mOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mSerialPort != null) mSerialPort.close();
    }
}
